package redsig.hash;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;

/**
 * RandomTree class used to create a GGM tree to calculate all salts needed for each node
 * @author  Florian Bacher & Matthias Vavti
 * @version  1.0
 */
public class RandomTree {
	private static final byte L = 0;
	private static final byte R = 1;
	private byte[] salt = new byte[20];
	/**
	 * @uml.property  name="leftChild"
	 * @uml.associationEnd  
	 */
	private RandomTree leftChild;
	/**
	 * @uml.property  name="rightChild"
	 * @uml.associationEnd  
	 */
	private RandomTree rightChild;
	//private RandomTree parent;
	private boolean isLeaf;
	private MessageDigest digest;
	private int depth;
	
	/**
	 * 
	 * @param nrSalts
	 * @throws NoSuchAlgorithmException
	 */
	public RandomTree(int nrSalts, byte[] salt) throws NoSuchAlgorithmException{
		//calculate depth of the tree
		double ddepth = Math.log10(nrSalts)/Math.log10(2);
		depth = (int)ddepth + 1;
		this.salt = salt;
		
		//check if depth > 0
		if(depth > 0){
			//append left child
			leftChild = new RandomTree(depth-1, this.salt, L, this);
			//append right child
			rightChild = new RandomTree(depth-1, this.salt, R, this);
		}
		else{
			//if depth = 0, it's a leaf
			isLeaf = true;
		}
	}

	/**
	 * 
	 * @param depth
	 * @param salt
	 * @param constant
	 * @param parent
	 * @throws NoSuchAlgorithmException
	 */
	public RandomTree(int depth, byte[] salt, byte constant, RandomTree parent) throws NoSuchAlgorithmException {
		//this.parent = parent;
		this.depth = depth;
		digest = MessageDigest.getInstance("SHA-256");
		digest.reset();
		digest.update(constant);
		this.salt = digest.digest(salt);
		if(depth > 0){
			leftChild = new RandomTree(depth-1, this.salt, L, this);
			rightChild = new RandomTree(depth-1, this.salt, R, this);
		}
		else{
			isLeaf = true;
		}
	}
	
	public ArrayList<byte[]> getSalts(){
		//int nrSalts = 2^depth;
		ArrayList<byte[]> salts = new ArrayList<byte[]>();
		if(isLeaf)
			salts.add(this.salt);
		else{
			ArrayList<byte[]> leftChildSalts = leftChild.getSalts();
			ArrayList<byte[]> rightChildSalts = rightChild.getSalts();
			
			for(byte[] salt : leftChildSalts)
				salts.add(salt);
			for(byte[] salt : rightChildSalts)
				salts.add(salt);
		}
		return salts;
	}
	

}
